<?php
// +-------------------------------------------------------------+
// | Tinysupe [ SIMPLE IS THE BEST ! ]
// +-------------------------------------------------------------+
// | Copyright (c) 2012 www.srccn.com All rights reserved.
// +-------------------------------------------------------------+
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +-------------------------------------------------------------+
// | Author: tinysu <tinysu@qq.com>
// +-------------------------------------------------------------+

define('QQWRYDAT', realpath(dirname(__FILE__)).'/qqwry.dat');

function qqwry_ip2addr($ipaddr) {
	// - Invalid IP data file
	if(!$fd = @fopen(QQWRYDAT, 'rb')) return false;
	// - Invalid IP Address
	if(!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $ipaddr)) return false;
	
	$ipaddr = explode('.', $ipaddr);
	// - Local area IP Address
	if($ipaddr[0] == 10 || $ipaddr[0] == 127 || ($ipaddr[0] == 192 && $ipaddr[1] == 168) ||
		($ipaddr[0] == 172 && ($ipaddr[1] >= 16 && $ipaddr[1] <= 31))) return false;
	// - Invalid IP Address
	if($ipaddr[0] > 255 || $ipaddr[1] > 255 || $ipaddr[2] > 255 || $ipaddr[3] >255) {
		return false;
	}

    $ipNum = $ipaddr[0] * 16777216 + $ipaddr[1] * 65536 + $ipaddr[2] * 256 + $ipaddr[3];

    if(!($datBegin = fread($fd, 4)) || !($datEnd = fread($fd, 4)) ) return false;

    @$ipbegin = implode('', unpack('L', $datBegin));
    if($ipbegin < 0) $ipbegin += pow(2, 32);

    @$ipend = implode('', unpack('L', $datEnd));
    if($ipend < 0) $ipend += pow(2, 32);

    $ipAllNum = ($ipend - $ipbegin) / 7 + 1;
	$numBegin = $ip2num = $ip1num = 0;
    $ipAddr1 = $ipAddr2 = '';
    $numEnd = $ipAllNum;

    while($ip1num > $ipNum || $ip2num < $ipNum) {
        $Middle= intval(($numEnd + $numBegin) / 2);
		fseek($fd, $ipbegin + 7 * $Middle);
		
        $ipData1 = fread($fd, 4);
		// - System Error
        if(strlen($ipData1) < 4) {
            fclose($fd);
            return false;
        }
		
        $ip1num = implode('', unpack('L', $ipData1));
        if($ip1num < 0) $ip1num += pow(2, 32);
        if($ip1num > $ipNum) {
            $numEnd = $Middle;
            continue;
        }
		
		$datSeek = fread($fd, 3);
		// - System Error
        if(strlen($datSeek) < 3) {
            fclose($fd);
            return false;
        }
		
        $datSeek = implode('', unpack('L', $datSeek.chr(0)));
        fseek($fd, $datSeek);
        $ipData2 = fread($fd, 4);
		// - System Error
        if(strlen($ipData2) < 4) {
            fclose($fd);
            return false;
        }
		
        $ip2num = implode('', unpack('L', $ipData2));
        if($ip2num < 0) $ip2num += pow(2, 32);
		// - Unknown
        if($ip2num < $ipNum) {
            if($Middle == $numBegin) {
                fclose($fd);
                return false;
            }
            $numBegin = $Middle;
        }
    }
	
	$ipFlag = fread($fd, 1);
    if($ipFlag == chr(1)) {
        $ipSeek = fread($fd, 3);
		// - System Error
        if(strlen($ipSeek) < 3) {
            fclose($fd);
            return false;
        }

        $ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
        fseek($fd, $ipSeek);
        $ipFlag = fread($fd, 1);
    }

    if($ipFlag == chr(2)) {
        $AddrSeek = fread($fd, 3);
		// - System Error
        if(strlen($AddrSeek) < 3) {
            fclose($fd);
            return false;
        }
        $ipFlag = fread($fd, 1);
        if($ipFlag == chr(2)) {
            $AddrSeek2 = fread($fd, 3);
			// - System Error
            if(strlen($AddrSeek2) < 3) {
                fclose($fd);
                return false;
            }

            $AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
            fseek($fd, $AddrSeek2);
        } else {
            fseek($fd, -1, SEEK_CUR);
        }

        while(($char = fread($fd, 1)) != chr(0))
        	$ipAddr2 .= $char;

		$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
        fseek($fd, $AddrSeek);
        while(($char = fread($fd, 1)) != chr(0))
        	$ipAddr1 .= $char;
    } else {
        fseek($fd, -1, SEEK_CUR);
        while(($char = fread($fd, 1)) != chr(0))
        	$ipAddr1 .= $char;
			
		$ipFlag = fread($fd, 1);
        if($ipFlag == chr(2)) {
            $AddrSeek2 = fread($fd, 3);
			// - System Error
            if(strlen($AddrSeek2) < 3) {
                fclose($fd);
                return false;
            }

            $AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
            fseek($fd, $AddrSeek2);
        } else {
            fseek($fd, -1, SEEK_CUR);
        }

        while(($char = fread($fd, 1)) != chr(0))
        	$ipAddr2 .= $char;
    }
    fclose($fd);

    if(preg_match('/http/i', $ipAddr2)) {
        $ipAddr2 = '';
    }
    $ipaddr = "$ipAddr1 $ipAddr2";
    $ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
    $ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
    $ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
	// - Unknown
    if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
        return false;
    }
    return mb_convert_encoding($ipaddr, 'utf-8', 'gb2312');
}
?>